#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <list>
#include <cstdio>
#include <exception>
#include <pthread.h>
#include "locker.h"
#include <iostream>

using namespace std;

// 线程池类，将其定义为模板类是为了代码复用，模板参数T是任务类
template<typename T>
class threadpool{
public:
    // thread_number是线程池中线程的数量，max_requests是请求队列中最多允许的、等待处理的请求的数量
    threadpool(int thread_number=8, int max_requests=10000);
    ~threadpool();
    bool append(T* request); // 加入线程池，返回是否成功加入

private:
    // 工作线程运行的函数，它不断从工作队列中取出任务并执行任务
    static void* worker(void* arg); // worker调用threadpool::run()，work参数是threadpool*
    void run();

private:
    
    int m_thread_number;        // 线程的数量
    pthread_t* m_threads;       // 描述线程池的数组，大小为m_thread_number，thread_t用于声明线程ID
    int m_max_requests;         // 请求队列中最多允许的、等待处理的请求的数量  
    std::list<T*> m_workqueue;  // 请求队列
    locker m_queuelocker;       // 保护请求队列的互斥锁，locker是自定义互斥锁类
    sem m_queuestat;            // 是否有任务需要处理，sem是自定义信号量类
    bool m_stop;                // 是否结束线程
};

template<typename T>
threadpool<T>::threadpool(int thread_number, int max_requests):
        m_thread_number(thread_number),
        m_max_requests(max_requests),
        m_stop(false),
        m_threads(nullptr){
    
    if((thread_number<=0) || (max_requests<=0)){
        throw std::exception();
    }

    m_threads=new pthread_t[m_thread_number]; // pthread_t类型unsigned long int，用于声明线程ID
    if(!m_threads){
        throw std::exception();
    }

    // 创建thread_number个线程，并将他们设置为脱离线程。脱离线程:不向主线程返回信息,不需要主线程等待
    for(int i=0;i<thread_number;++i){
        cout<<"创建第"<<i<<"个线程"<<endl;
        if(pthread_create(m_threads+i, nullptr, worker, this) != 0){
            delete [] m_threads; // TODO
            throw exception();
        }
        // linux线程执行和windows不同，pthread有两种状态joinable状态和unjoinable状态，如果线程是joinable状态，当线程函数自己返回退出时或pthread_exit时都不会释放线程所占用堆栈和线程描述符（总计8K多）。只有当你调用了pthread_join之后这些资源才会被释放。若是unjoinable状态的线程，这些资源在线程函数退出时或pthread_exit时自动会被释放
        if(pthread_detach(m_threads[i])){// unjoinable属性可以在pthread_create时指定，或在线程创建后在线程中pthread_detach自己
            delete [] m_threads;
            throw exception();
        }
    }
}

template<typename T>
threadpool<T>::~threadpool(){
    delete [] m_threads;
    m_stop=true;
}

template<typename T>
bool threadpool<T>::append(T* request)
{
    // 操作工作队列时一定要加锁，因为所有线程共享工作队列
    m_queuelocker.lock();
    if(m_workqueue.size() > m_max_requests){
        m_queuelocker.unlock();
        return false;
    }
    m_workqueue.push_back(request);
    m_queuelocker.unlock();
    m_queuestat.post();
    return true;
}

template<typename T>
void* threadpool<T>::worker(void* arg)
{
    threadpool* pool=(threadpool*)arg;
    pool->run();
    return pool;
}

template<typename T>
void threadpool<T>::run(){

    while(!m_stop){
        m_queuestat.wait();
        m_queuelocker.lock();
        if(m_workqueue.empty()){
            m_queuelocker.unlock();
            continue;
        }
        T* request=m_workqueue.front();
        m_workqueue.pop_front();
        m_queuelocker.unlock();
        if(!request){
            continue;
        }
        request->process(); // 最终调用模板参数的T::process()处理
    }
}

#endif
